﻿using System;
using System.Web;
using System.Web.Security;
using Jayden.Dll.Core.Membership;
using Jayden.Dll.Web.Events;
using Jayden.Dll.Web.HtmlControls;
using Jayden.Dll.Web.Json;

namespace Jayden.Dll.Web.Controls
{
	public class LoginForm : Form
	{
		public delegate void OnLoginSuccess(HttpHandlerContext context, User user);
		public delegate void OnLoginFailed(HttpHandlerContext context);

		public class LoginCommandHandler : HttpCommandHandler
		{
			public LoginCommandHandler() : this("Login") { }
			public LoginCommandHandler(string command) : base(command)
			{
				RegisterEvent("LoginFailed");
				RegisterEvent("LoginSuccess");
			}
			public event OnLoginFailed LoginFailed { add { AddEvent<OnLoginFailed>("LoginFailed", value); } remove { RemoveEvent<OnLoginFailed>("LoginFailed", value); } }
			public event OnLoginSuccess LoginSuccess { add { AddEvent<OnLoginSuccess>("LoginSuccess", value); } remove { RemoveEvent<OnLoginSuccess>("LoginSuccess", value); } }

			protected override void ProcessCommand(HttpHandlerContext context, string command)
			{
				string username = context.Context.Request["username"];
				string password = context.Context.Request["password"];
				bool rememberMe = context.Context.Request["rememberMe"] == "on";

				bool validated = Membership.ValidateUser(username, password);
				User user = null;

				if (validated)
				{
					int minutes = rememberMe ? (15 * 24 * 60) : 30;
					FormsAuthenticationTicket tkt = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(minutes), rememberMe, username);
					string cookiestr = FormsAuthentication.Encrypt(tkt);
					HttpCookie ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
					if (rememberMe)
						ck.Expires = tkt.Expiration;
					ck.Path = FormsAuthentication.FormsCookiePath;
					context.Context.Response.Cookies.Add(ck);
					user = Membership.GetUser(username) as User;
					Invoke("LoginSuccess", context, user);
				}
				else
					Invoke("LoginFailed", context);
			}
		}

		private Input m_Username;
		private Input m_Password;
		private Input m_RememberMe;

		private Button m_Login;

		public override void Load(System.Xml.XmlNode node, HtmlControlLoader loader)
		{
			base.Load(node, loader);

			if (Id == null)
				Id = "loginForm";

			m_Username = GetFormElement<Input>("username");
			m_Password = GetFormElement<Input>("password");
			m_RememberMe = GetFormElement<Input>("rememberMe");
			m_Login = GetFormElement<Button>("login", "command");

			m_Username.Id = m_Username.ServerId;
			m_Password.Id = m_Password.ServerId;
			m_RememberMe.Id = m_RememberMe.ServerId;
			m_Login.Id = m_Login.ServerId;
		}

		public void LinkLabels()
		{
			FindLabel(m_Username);
			FindLabel(m_Password);
			FindLabel(m_RememberMe);
		}

		private void DisableFields()
		{
			m_Username.Enabled = false;
			m_Password.Enabled = false;
			m_RememberMe.Enabled = false;
			m_Login.Enabled = false;
		}

		public override void ProcessHtmlRequest(HttpHandlerContext context)
		{
			base.ProcessHtmlRequest(context);
			LinkLabels();
			LoginCommandHandler handler = context.HandlerManager.GetHandler<LoginCommandHandler>();
			handler.LoginSuccess += new OnLoginSuccess(LoginSuccess);
			if (context.Context.User.Identity.IsAuthenticated)
				DisableFields();
		}

		public override void  ProcessJsonRequest(HttpHandlerContext context)
		{
			base.ProcessJsonRequest(context);
			LinkLabels();
			LoginCommandHandler handler = context.HandlerManager.GetHandler<LoginCommandHandler>();
			handler.LoginSuccess += new OnLoginSuccess(LoginSuccess);
		}

		public override void ProcessJsRequest(HttpHandlerContext context)
		{
			base.ProcessJsRequest(context);
			if (!context.Js.Contains(Id))
			{
				context.Js[Id].AppendAjaxHandler(@"
		if(data.login) {
			if(data.login.success) {
				$('#" + m_Username.Id + @"').attr('disabled', 'disabled');
				$('#" + m_Password.Id + @"').attr('disabled', 'disabled');
				$('#" + m_RememberMe.Id + @"').attr('disabled', 'disabled');
				$('#" + m_Login.Id + @"').attr('disabled', 'disabled');
			}
			if(data.login.alert) {
				alert(data.login.alert);
			}
			if(data.login.href) {
				window.location.href = data.login.href;
			}
		} else if(data.logout) {
			$('#" + m_Username.Id + @"').removeAttr('disabled');
			$('#" + m_Password.Id + @"').removeAttr('disabled');
			$('#" + m_RememberMe.Id + @"').removeAttr('disabled');
			$('#" + m_Login.Id + @"').removeAttr('disabled');
		}
");
				context.Js[Id].AppendOnInit(@"
	var $login = $('#"+ m_Login.Id + @"');
	$('#" + Id + @"').submit(function(e) {
		e.preventDefault();
		return JAYDEN.sfn.submitAjax(this, $login);
	});
");
			}
		}

		private void LoginSuccess(HttpHandlerContext context, User user)
		{
			if (context.RequestType == Enums.HttpRequestType.Html)
			{
				DisableFields();
				if (!string.IsNullOrWhiteSpace(context.Request["returnUrl"]))
					context.Context.Response.Redirect(context.Request["returnUrl"], true);
				AddText<P>("You are now authenticated as " + user.UserName);
			}
			else if (context.RequestType == Enums.HttpRequestType.Json)
			{
				if (!context.Json.ContainsKey("login"))
				{
					JsonObject login = new JsonObject();
					login.Add("success", true);
					login.Add("alert", "You are now authenticated as " + user.UserName + ".");
					if (!string.IsNullOrWhiteSpace(context.Request["returnUrl"]))
						login.Add("href", context.Request["returnUrl"]);
					context.Json.Add("login", login);
				}
			}
		}

	}
}
